package rrrmai.di.module;

import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.f2prateek.rx.preferences2.RxSharedPreferences;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.xgggh.rrrmai.BuildConfig;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Authenticator;
import okhttp3.Cache;
import okhttp3.Credentials;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
import rrrmai.di.annotation.ScopeActivity;
import rrrmai.net.constant.Constant;
import rrrmai.net.http.HttpAgent;
import rrrmai.net.http.LiveNetworkMonitor;
import rrrmai.net.http.NetworkMonitor;
import rrrmai.net.http.NoNetworkException;
import rrrmai.net.http.SSLSocketClient;
import rrrmai.net.http.adapter.NullStringToEmptyAdapterFactory;
import xgggh.activity.DIApplication;

/**
 * Created by summer on 2018/2/9.
 */
@Module
public class NetworkModule {
    public NetworkModule(){
    }

    @Provides
    //@Singleton
    SharedPreferences providesSharedPreferences(DIApplication application) {
        return PreferenceManager.getDefaultSharedPreferences(application);
    }

    @Provides
    //@Singleton
    Cache provideCache(DIApplication context) {
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        Cache cache = new Cache(context.getCacheDir(), cacheSize);
        return cache;
    }

    @Provides
    //@Singleton
    Retrofit provideRetrofit(OkHttpClient okHttpClient,@Named("domain") String domain) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory<>())
                .create();
       return new Retrofit.Builder()
                .baseUrl(domain)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
                .build();
    }


    @Provides
    //@Singleton
    OkHttpClient provideOkHttpClient(Cache cache
            //, ClearableCookieJar cookieJar
            , @Named("tokenAgentInterceptor")Interceptor tokenAgentInterceptor
    ,final NetworkMonitor networkMonitor) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .authenticator(new Authenticator() {
                    @Override
                    public Request authenticate(Route route, Response response) throws IOException {
                        String credential = Credentials.basic("clientId", "clientSecret");
                        return response.request().newBuilder()
                                .header("Authorization", credential)
                                .build();
                    }
                })
                .connectTimeout(15, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .readTimeout(30, TimeUnit.SECONDS)
                .cache(cache)
                .sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
                .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
               // .cookieJar(cookieJar)
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        boolean connected = networkMonitor.isConnected();
                        if (connected) {
                            try{
                                return chain.proceed(chain.request());
                            }catch (IOException e){
                                  throw new NoNetworkException(e.getMessage());
                            }
                        } else {
                            throw new NoNetworkException("无网络连接");
                        }
                    }
                })
                .addInterceptor(tokenAgentInterceptor)
                .addInterceptor(new HttpLoggingInterceptor().setLevel(BuildConfig.DEBUG? HttpLoggingInterceptor.Level.BODY: HttpLoggingInterceptor.Level.NONE))
                .build();

        return okHttpClient;
    }


    @Provides
    //@Singleton
    NetworkMonitor provideNetworkMonitor(DIApplication context) {
        return new LiveNetworkMonitor(context);
    }

    @Provides
    //@Singleton
    @Named("userAgent")
    String provideUserAgent(DIApplication context) {
        return HttpAgent.getUserAgent(context);
    }




    @Provides
    //@Singleton
    @Named("tokenAgentInterceptor")
    Interceptor provideTokenAgentInterceptor(final @Named("userAgent") String userAgent,final RxSharedPreferences mRxSharedPreferences) {
        return  new Interceptor(){
            @Override
            public Response intercept(final Chain chain) throws IOException {
                Request originalRequest = chain.request();
                String method= originalRequest.method();
                Request.Builder requestBuilder = originalRequest.newBuilder();

                String _token =mRxSharedPreferences.getString(Constant.Token).get();
                //User-Agent: okhttp/3.8.0
                requestBuilder.header("User-Agent",userAgent);
                requestBuilder.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
                requestBuilder.header("Connection","close");
                //form
                if("POST".equals(method) && originalRequest.body() instanceof FormBody){
                    FormBody formBody= (FormBody) originalRequest.body();
                    FormBody.Builder newFormBody = new FormBody.Builder();
                    for (int i = 0; i <formBody.size() ; i++) {
                        newFormBody.addEncoded(formBody.encodedName(i),formBody.encodedValue(i));
                    }
                    newFormBody.add("client","android");
                    if (!TextUtils.isEmpty(_token)
                            &&
                            !originalRequest.url().toString().contains("getVcodeToken")){
                        newFormBody.add("token",_token);
                    }
                    requestBuilder.method(method,newFormBody.build());
                  try {
                      return chain.proceed(requestBuilder.build());
                  }catch (Exception e){
                      throw new NoNetworkException(e.getMessage());
                  }
                }

                HttpUrl originalHttpUrl = originalRequest.url();
                HttpUrl.Builder _builder= originalHttpUrl.newBuilder()
                        .addQueryParameter("client","android");
                if (!TextUtils.isEmpty(_token)
                        &&
                        !originalRequest.url().toString().contains("getVcodeToken")) {
                    _builder.addQueryParameter("token", _token);
                }

                Request request = requestBuilder
                        .url(_builder.build())
                        .method(originalRequest.method(), originalRequest.body())
                        .header("Authorization", "Bearer "+"5286535a-8c91-4014-8ca5-ee738e06bd2b")
                        .build();

               try {
                   return chain.proceed(request);
               }catch (Exception e){
                   throw new NoNetworkException(e.getMessage());
               }
            }
        };
    }

  /*  @Provides
    @Singleton
    ClearableCookieJar provideCookieJar(DIApplication application) {
        ClearableCookieJar cookieJar =
                new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(application));
        return cookieJar;
    }*/

    @Provides
    @Named("domain")
    public String  providesDomain() {
        return BuildConfig.domain;
    }
}
